package org.MyJunit.handle;

import org.MyJunit.Annotation.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class HandleAnnotation {
    public static void handleTest(Class<?> clazz) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        // 确保类有默认构造函数
        //Object instance = clazz.getDeclaredConstructor().newInstance();
        //实例化在代码开头，先创建测试类实例，再执行测试方法，即先执行构造方法，再执行其他测试方法

        // 获取类中的所有方法
        Method[] methods = clazz.getDeclaredMethods();

        Method beforeClassMethod = null;
        Method afterClassMethod = null;
        List<Method> beforeMethods = new ArrayList<>();
        List<Method> testMethods = new ArrayList<>();
        List<Method> afterMethods = new ArrayList<>();

        // 遍历方法，分类存储不同注解的方法
        for (Method method : methods) {
            if (method.isAnnotationPresent(MyBeforeClass.class)) {  //isAnnotationPresent() 方法用于检查方法是否被指定的注解修饰 是返回true，否返回false
                if (beforeClassMethod == null) {
                    beforeClassMethod = method;
                }

            } else if (method.isAnnotationPresent(MyBefore.class)) {
                beforeMethods.add(method);
            } else if (method.isAnnotationPresent(MyTest.class)) {
                testMethods.add(method);
            } else if (method.isAnnotationPresent(MyAfter.class)) {
                afterMethods.add(method);
            } else if (method.isAnnotationPresent(MyAfterClass.class)) {
                if (afterClassMethod == null) {
                    afterClassMethod = method;
                }

            }
        }

        // 执行 @MyBeforeClass 方法
        if (beforeClassMethod != null) {
            checkStaticMethod(beforeClassMethod, MyBeforeClass.class);  //检查方法是否为静态方法
            beforeClassMethod.invoke(null);
        }



        // 执行每个测试方法，每次测试前执行 @MyBefore，测试后执行 @MyAfter
        for (Method testMethod : testMethods) {

            // 确保类有默认构造函数
            Object instance = clazz.getDeclaredConstructor().newInstance();

            // 执行 @MyBefore 方法
            for (Method beforeMethod : beforeMethods) {
                beforeMethod.invoke(instance);
            }

            // 执行 @MyTest 方法
            testMethod.invoke(instance);

            // 执行 @MyAfter 方法
            for (Method afterMethod : afterMethods) {
                afterMethod.invoke(instance);
            }
        }

        // 执行 @MyAfterClass 方法
        if (afterClassMethod != null) {
            checkStaticMethod(afterClassMethod, MyAfterClass.class);  //检查方法是否为静态方法
            afterClassMethod.invoke(null);
        }
    }

    private static void checkStaticMethod(Method method, Class<? extends Annotation> annotationClass) {
        if (!java.lang.reflect.Modifier.isStatic(method.getModifiers())) {
            throw new IllegalStateException("@" + annotationClass.getSimpleName() + " method " + method.getName() + " must be static");
        }
    }
}